package repository

import (
	"fitness/go-admin/internal/model"
	"fitness/go-admin/pkg/cache"
	"fmt"
	"time"

	"gorm.io/gorm"
)

type MemberRepository interface {
	Create(member *model.Member) error
	Update(member *model.Member) error
	Delete(id uint) error
	GetByID(id uint) (*model.Member, error)
	GetByPhone(phone string) (*model.Member, error)
	List(page, pageSize int) ([]model.Member, int64, error)
	GetByUserID(userID uint) (*model.Member, error)
}

type memberRepository struct {
	db *gorm.DB
}

func NewMemberRepository(db *gorm.DB) MemberRepository {
	return &memberRepository{db: db}
}

func (r *memberRepository) Create(member *model.Member) error {
	return r.db.Create(member).Error
}

func (r *memberRepository) Update(member *model.Member) error {
	if err := r.db.Save(member).Error; err != nil {
		return err
	}

	// 清除缓存
	cache.DeleteCache(fmt.Sprintf("member:id:%d", member.ID))
	cache.DeleteCache(fmt.Sprintf("member:phone:%s", member.Phone))
	cache.DeletePattern("member:list:*")

	return nil
}

func (r *memberRepository) Delete(id uint) error {
	return r.db.Delete(&model.Member{}, id).Error
}

// GetByID - 热点数据缓存
func (r *memberRepository) GetByID(id uint) (*model.Member, error) {
	// 缓存key
	cacheKey := fmt.Sprintf("member:id:%d", id)
	var member model.Member

	// 尝试从缓存获取
	if err := cache.GetJSON(cacheKey, &member); err == nil {
		return &member, nil // 缓存命中
	}

	// 查询数据库
	err := r.db.First(&member, id).Error
	if err != nil {
		return nil, err
	}

	// 写入缓存（10分钟，会员信息变化不频繁）
	_ = cache.SetJSON(cacheKey, member, 10*time.Minute)

	return &member, nil
}

// GetByPhone - 手机号查询也缓存
func (r *memberRepository) GetByPhone(phone string) (*model.Member, error) {
	// 手机号查询也可以缓存
	cacheKey := fmt.Sprintf("member:phone:%s", phone)
	var member model.Member

	if err := cache.GetJSON(cacheKey, &member); err == nil {
		return &member, nil // 缓存命中
	}

	err := r.db.Where("phone = ?", phone).First(&member).Error
	if err != nil {
		return nil, err
	}

	// 写入缓存（10分钟）
	_ = cache.SetJSON(cacheKey, member, 10*time.Minute)

	return &member, nil
}

func (r *memberRepository) GetByUserID(userID uint) (*model.Member, error) {
	var member model.Member
	err := r.db.Where("user_id = ?", userID).First(&member).Error
	return &member, err
}

func (r *memberRepository) List(page, pageSize int) ([]model.Member, int64, error) {
	var members []model.Member
	var total int64

	offset := (page - 1) * pageSize

	if err := r.db.Model(&model.Member{}).Count(&total).Error; err != nil {
		return nil, 0, err
	}

	err := r.db.Offset(offset).Limit(pageSize).Order("created_at DESC").Find(&members).Error
	return members, total, err
}
